package cn.chrilwe.pigpig.im.server;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;

import cn.chrilwe.pigpig.im.Main;
import cn.chrilwe.pigpig.im.config.ServerConfig;
import cn.chrilwe.pigpig.im.ex.PortNotSetEx;
import cn.chrilwe.pigpig.im.ex.ServerConfigNullPointerEx;
import cn.chrilwe.pigpig.im.ex.WsUrlNotSetEx;
import cn.chrilwe.pigpig.im.filters.Filter;
import cn.chrilwe.pigpig.im.listener.impl.ServerLifecycleListener;
import cn.chrilwe.pigpig.im.server.handler.ServerChannelInilizer;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;

/**
 * 
 * @author chrilwe 2020-7-25 websocker服务器
 */
public class WebSocketServer implements Server {

	public static ServerConfig serverConfig;
	public static ApplicationContext applicationContext;
	public static List<Filter> sortFilters;

	public WebSocketServer(ServerConfig serverConfig, ApplicationContext ac, List<Filter> sortFilters) {
		this.serverConfig = serverConfig;
		this.applicationContext = ac;
		this.sortFilters = sortFilters;
	}

	@Override
	public void start() {
		ServerLifecycleListener listener = new ServerLifecycleListener();
		listener.setContext(applicationContext);
		listener.setServerConfig(serverConfig);
		listener.start();
		if (serverConfig == null) {
			throw new ServerConfigNullPointerEx("serverconfig can not be null", 200);
		}
		int port = serverConfig.getPort();
		if (port <= 0) {
			throw new PortNotSetEx("port is not set", 201);
		}
		String wsUrl = serverConfig.getWsUrl();
		if (StringUtils.isEmpty(wsUrl)) {
			throw new WsUrlNotSetEx("ws url not set", 202);
		}
		realStart(serverConfig,listener);
	}

	protected void realStart(ServerConfig serverConfig, ServerLifecycleListener listener) {
		EventLoopGroup bossGroup = new NioEventLoopGroup(1);
		EventLoopGroup workGroup = new NioEventLoopGroup();

		try {
			ServerBootstrap strap = new ServerBootstrap();
			strap.group(bossGroup, workGroup).channel(NioServerSocketChannel.class)
					.childHandler(new ServerChannelInilizer(serverConfig.getWsUrl()));

			ChannelFuture channelFuture = strap.bind(serverConfig.getPort()).sync();
			listener.end();
			channelFuture.channel().closeFuture().sync();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			if (workGroup != null) {
				workGroup.shutdownGracefully();
			}
			if (bossGroup != null) {
				bossGroup.shutdownGracefully();
			}
		}
	}

}
